home *** CD-ROM | disk | FTP | other *** search
/ CD/PC Actual 76 / DVD Actual 1 Marzo 2003.iso / Trial / TurboCAD 7.1 Pro / Data.Cab / F24822_Autorect.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-10  |  27.7 KB  |  1,044 lines

  1. /******************************************************************/
  2. /*                                                                */
  3. /*                      TurboCAD for Windows                      */
  4. /*                   Copyright (c) 1993 - 1999                    */
  5. /*             International Microcomputer Software, Inc.         */
  6. /*                            (IMSI)                              */
  7. /*                      All rights reserved.                      */
  8. /*                                                                */
  9. /******************************************************************/
  10. // AutoRect.cpp : implementation file
  11. //
  12.  
  13. #include "stdafx.h"
  14. #include "RRect.h"
  15. #include "AutoRect.h"  // This class
  16. #include "RectPage.h"  // Property page class
  17. #include "GxIntf.h"   // TurboCAD interfaces (forward declarations)
  18. #include "Imsigx.h"   // TurboCAD interfaces
  19. #include <math.h>
  20.  
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. // Standard variants
  28. COleVariant t(-1L, VT_BOOL);
  29. COleVariant f(0L, VT_BOOL);
  30. COleVariant z(0.0);
  31. COleVariant missing((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
  32. const double PI = 3.14159265;
  33.  
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CAutoRect
  36.  
  37. const IID IID_IGraphic = 
  38.     {0x6A481109,0xE531,0x11CF,{0xA1,0x15,0x00,0xA0,0x24,0x15,0x8D,0xAF}};
  39.  
  40. IMPLEMENT_DYNCREATE(CAutoRect, CCmdTarget)
  41.  
  42. CAutoRect::CAutoRect() :
  43.     m_pRectPage(NULL)
  44. {
  45.     EnableAutomation();
  46.  
  47.     // To keep the application running as long as an OLE automation 
  48.     //    object is active, the constructor calls AfxOleLockApp.
  49.     
  50.     AfxOleLockApp();
  51. }
  52.  
  53. CAutoRect::~CAutoRect()
  54. {
  55.     // To terminate the application when all objects created with
  56.     //     with OLE automation, the destructor calls AfxOleUnlockApp.
  57.     
  58.     AfxOleUnlockApp();
  59. }
  60.  
  61.  
  62. void CAutoRect::OnFinalRelease()
  63. {
  64.     // When the last reference for an automation object is released
  65.     // OnFinalRelease is called.  The base class will automatically
  66.     // deletes the object.  Add additional cleanup required for your
  67.     // object before calling the base class.
  68.  
  69.     CCmdTarget::OnFinalRelease();
  70. }
  71.  
  72.  
  73. BEGIN_MESSAGE_MAP(CAutoRect, CCmdTarget)
  74.     //{{AFX_MSG_MAP(CAutoRect)
  75.         // NOTE - the ClassWizard will add and remove mapping macros here.
  76.     //}}AFX_MSG_MAP
  77. END_MESSAGE_MAP()
  78.  
  79. BEGIN_DISPATCH_MAP(CAutoRect, CCmdTarget)
  80.     //{{AFX_DISPATCH_MAP(CAutoRect)
  81.     DISP_PROPERTY_EX(CAutoRect, "ClassID", GetClassID, SetNotSupported, VT_BSTR)
  82.     DISP_PROPERTY_EX(CAutoRect, "Description", GetDescription, SetNotSupported, VT_BSTR)
  83.     DISP_FUNCTION(CAutoRect, "GetPropertyInfo", GetPropertyInfo, VT_I4, VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT)
  84.     DISP_FUNCTION(CAutoRect, "GetPageInfo", GetPageInfo, VT_I4, VTS_DISPATCH VTS_PI4 VTS_PVARIANT)
  85.     DISP_FUNCTION(CAutoRect, "GetWizardInfo", GetWizardInfo, VT_I4, VTS_PVARIANT)
  86.     DISP_FUNCTION(CAutoRect, "GetEnumNames", GetEnumNames, VT_I4, VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  87.     DISP_FUNCTION(CAutoRect, "PageControls", PageControls, VT_BOOL, VTS_DISPATCH VTS_DISPATCH VTS_I4 VTS_BOOL)
  88.     DISP_FUNCTION(CAutoRect, "PageDone", PageDone, VT_EMPTY, VTS_DISPATCH VTS_PVARIANT)
  89.     DISP_FUNCTION(CAutoRect, "PropertyPages", PropertyPages, VT_BOOL, VTS_DISPATCH VTS_PVARIANT)
  90.     DISP_FUNCTION(CAutoRect, "Wizard", Wizard, VT_BOOL, VTS_DISPATCH VTS_PVARIANT)
  91.     DISP_FUNCTION(CAutoRect, "OnGeometryChanged", OnGeometryChanged, VT_EMPTY, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  92.     DISP_FUNCTION(CAutoRect, "OnGeometryChanging", OnGeometryChanging, VT_BOOL, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  93.     DISP_FUNCTION(CAutoRect, "OnNewGraphic", OnNewGraphic, VT_BOOL, VTS_DISPATCH VTS_BOOL)
  94.     DISP_FUNCTION(CAutoRect, "OnCopyGraphic", OnCopyGraphic, VT_BOOL, VTS_DISPATCH VTS_DISPATCH)
  95.     DISP_FUNCTION(CAutoRect, "OnPropertyChanged", OnPropertyChanged, VT_EMPTY, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  96.     DISP_FUNCTION(CAutoRect, "OnPropertyChanging", OnPropertyChanging, VT_BOOL, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  97.     DISP_FUNCTION(CAutoRect, "OnPropertyGet", OnPropertyGet, VT_EMPTY, VTS_DISPATCH VTS_I4)
  98.     DISP_FUNCTION(CAutoRect, "Draw", Draw, VT_BOOL, VTS_DISPATCH VTS_DISPATCH VTS_PVARIANT)
  99.     DISP_FUNCTION(CAutoRect, "Regen", Regen, VT_EMPTY, VTS_DISPATCH)
  100.     DISP_FUNCTION(CAutoRect, "Initialize", Initialize, VT_BOOL, VTS_DISPATCH)
  101.     //}}AFX_DISPATCH_MAP
  102. END_DISPATCH_MAP()
  103.  
  104. // Note: we add support for IID_ISmartObjectServer to support typesafe binding
  105. //  from VBA.  This IID must match the GUID that is attached to the 
  106. //  dispinterface in the .ODL file.
  107.  
  108. // {6A481303-E531-11CF-A115-00A024158DAF}
  109. static const IID IID_ISmartObjectServer =
  110. {0x6A481303,0xE531,0x11CF,{0xA1,0x15,0x00,0xA0,0x24,0x15,0x8D,0xAF}};
  111.  
  112. BEGIN_INTERFACE_MAP(CAutoRect, CCmdTarget)
  113.     INTERFACE_PART(CAutoRect, IID_ISmartObjectServer, Dispatch)
  114. END_INTERFACE_MAP()
  115.  
  116. // {7724BB46-B671-11D0-9B3B-444553540000}
  117. //IMPLEMENT_OLECREATE(CAutoRect, "RRect.Rectangle", 0x7724bb46, 0xb671, 0x11d0, 0x9b, 0x3b, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
  118. IMPLEMENT_OLECREATE(CAutoRect, "RRect.Rectangle", 0x7724bb36, 0xb671, 0x11d0, 0x9b, 0x3b, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);//# Non-localizable string#
  119.  
  120. /////////////////////////////////////////////////////////////////////////////
  121. // CAutoRect message handlers
  122.  
  123. BSTR CAutoRect::GetClassID() 
  124. {
  125.     // Convert our GUID (see IMPLEMENT_OLECREATE macro) to a string
  126.     LPOLESTR olestr;
  127.     HRESULT hRes = ::StringFromCLSID(guid, &olestr);
  128.     if (FAILED(hRes))
  129.         return NULL;
  130.  
  131.     BSTR bstr = ::SysAllocString(olestr);
  132.     CoTaskMemFree(olestr);
  133.     return bstr;
  134. }
  135.  
  136. BSTR CAutoRect::GetDescription() 
  137. {
  138.     // Get the description from the resource
  139.     CString strResult;
  140.     strResult.LoadString(IDS_AUTORECT_DESCRIPTION);
  141.  
  142.     return strResult.AllocSysString();
  143. }
  144.  
  145. const long VT_INTEGER_ENUM = VT_I2 + 100;
  146. const long VT_LONG_ENUM = VT_I4 + 100;
  147. const long VT_STRING_ENUM = VT_BSTR + 100;
  148.  
  149. const long GF_COSMETIC = 128;
  150.  
  151. enum StockPages {
  152.     PP_STOCK_PEN = 1,
  153.     PP_STOCK_BRUSH = 2,
  154.     PP_STOCK_TEXT = 4,
  155.     PP_STOCK_INSERT = 8,
  156.     PP_STOCK_VIEWPORT = 16,
  157.     PP_STOCK_AUTO = 32
  158. };
  159.  
  160. const long nProperties = 1;
  161.  
  162. enum PropertyIDs 
  163. {
  164.    idRoundness = 1,
  165. };
  166.  
  167. long CAutoRect::GetPropertyInfo(VARIANT FAR* Names, VARIANT FAR* Types, VARIANT FAR* IDs, VARIANT FAR* Defaults) 
  168. {
  169.      ASSERT(Names->vt == VT_ARRAY|VT_BSTR);
  170.     ASSERT(Types->vt == VT_ARRAY|VT_I4);
  171.     ASSERT(IDs->vt == VT_ARRAY|VT_I4);
  172.     ASSERT(Defaults->vt == VT_ARRAY|VT_VARIANT);
  173.  
  174.      SAFEARRAYBOUND bound = { nProperties, 0 };
  175.     if (FAILED(::SafeArrayRedim(Names->parray, &bound)))
  176.         return 0;
  177.     if (FAILED(::SafeArrayRedim(Types->parray, &bound)))
  178.         return 0;
  179.     if (FAILED(::SafeArrayRedim(IDs->parray, &bound)))
  180.         return 0;
  181.     if (FAILED(::SafeArrayRedim(Defaults->parray, &bound)))
  182.         return 0;
  183.  
  184.     BSTR* rgNames;
  185.     long* rgTypes;
  186.     long* rgIDs;
  187.     VARIANT* rgDefaults; 
  188.     long lReturn = 0;
  189.     if (SUCCEEDED(::SafeArrayAccessData(Names->parray, (void**)&rgNames)))
  190.     {
  191.         if (SUCCEEDED(::SafeArrayAccessData(Types->parray, (void**)&rgTypes)))
  192.         {
  193.             if (SUCCEEDED(::SafeArrayAccessData(IDs->parray, (void**)&rgIDs)))
  194.             {
  195.                 if (SUCCEEDED(::SafeArrayAccessData(Defaults->parray, (void**)&rgDefaults)))
  196.                 {
  197.                     CString strStr;
  198.                     strStr.LoadString(IDS_STRING3);
  199.                     //rgNames[0] = ::SysAllocString(OLESTR("Roundness"));//# Localizable string#
  200.                     rgNames[0] = ::SysAllocString(strStr.AllocSysString());
  201.                     rgTypes[0] = VT_R8;
  202.                     rgIDs[0] = idRoundness;
  203.                     rgDefaults[0].vt = VT_R8;
  204.                     rgDefaults[0].dblVal = 50.0;
  205.  
  206.                     ::SafeArrayUnaccessData(Defaults->parray);
  207.                     lReturn = nProperties;
  208.                 }
  209.                 ::SafeArrayUnaccessData(IDs->parray);
  210.             }
  211.             ::SafeArrayUnaccessData(Types->parray);
  212.         }
  213.         ::SafeArrayUnaccessData(Names->parray);
  214.     }
  215.     return lReturn;
  216. }
  217.  
  218. long CAutoRect::GetPageInfo(LPDISPATCH /*AGraphic*/, long* StockPages, VARIANT FAR* Names) 
  219. {
  220.     ASSERT(StockPages != NULL);
  221.      ASSERT(Names->vt == VT_ARRAY|VT_BSTR);
  222.  
  223.     // Request pen page and auto page
  224.     *StockPages = PP_STOCK_PEN | PP_STOCK_AUTO;
  225.  
  226.      SAFEARRAYBOUND bound = { 1, 0 };
  227.     if (FAILED(::SafeArrayRedim(Names->parray, &bound)))
  228.         return 0;
  229.  
  230.     CString strCaption;
  231.     strCaption.LoadString(IDS_AUTORECT_CAPTION);
  232.     BSTR bstrCaption = strCaption.AllocSysString();
  233.  
  234.     long lIndex = 0;
  235.     if (FAILED(SafeArrayPutElement(Names->parray, &lIndex, (void*)bstrCaption)))
  236.     {
  237.         ::SysFreeString(bstrCaption);
  238.         return 0;
  239.     }
  240.     return 1;
  241. }
  242.  
  243. long CAutoRect::GetWizardInfo(VARIANT FAR* Names) 
  244. {
  245.     // No wizards, nothing to do
  246.     return 0;
  247. }
  248.  
  249. long CAutoRect::GetEnumNames(long PropID, VARIANT FAR* Names, VARIANT FAR* Values) 
  250. {
  251.     // Should never be called!
  252.     return 0;
  253. }
  254.  
  255. double GetRoundness(IGraphic* pIGraphic)
  256. {
  257.     double roundness = 50.0;
  258.     Properties* pProps = NULL;
  259.     Property* pProp;
  260.     COleVariant varIndex, varValue;
  261.     if (SUCCEEDED(pIGraphic->get_Properties(&pProps)))
  262.     {
  263.         //varIndex = "Roundness";//# Localizable string#
  264.         CString strStr;
  265.         strStr.LoadString(IDS_STRING3);
  266.         varIndex = LPCTSTR(strStr);
  267.         if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  268.         {
  269.             if (SUCCEEDED(pProp->get_Value(0, &varValue)) &&
  270.                 varValue.vt == VT_R8)
  271.             {
  272.                 roundness = varValue.dblVal;
  273.             }
  274.             pProp->Release();
  275.         }
  276.         pProps->Release();
  277.     }
  278.     return roundness;
  279. }
  280.  
  281. void SetRoundness(IGraphic* pIGraphic, double roundness)
  282. {
  283.     Properties* pProps = NULL;
  284.     Property* pProp;
  285.     COleVariant varIndex;
  286.     if (SUCCEEDED(pIGraphic->get_Properties(&pProps)))
  287.     {
  288.         //varIndex = "Roundness";//# Localizable string#
  289.         CString strStr;
  290.         strStr.LoadString(IDS_STRING3);
  291.         varIndex = LPCTSTR(strStr);
  292.         if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  293.         {
  294.             COleVariant varValue;
  295.             varValue.vt = VT_R8;
  296.             varValue.dblVal = roundness;
  297.             pProp->put_Value(0, &varValue);
  298.             pProp->Release();
  299.         }
  300.         pProps->Release();
  301.     }
  302. }
  303.  
  304. BOOL CAutoRect::PageControls(LPDISPATCH ThisRegenMethod, LPDISPATCH AGraphic, long PageNumber, BOOL SaveProperties) 
  305. {
  306.     IGraphic* pIGraphic = NULL;
  307.     if (FAILED(AGraphic->QueryInterface(IID_IGraphic, (void**)&pIGraphic)))
  308.         return FALSE;
  309.  
  310.     BOOL bReturn = FALSE;
  311.     Properties* pProps = NULL;
  312.     Property* pProp;
  313.     COleVariant varIndex, varValue;
  314.     if (SUCCEEDED(pIGraphic->get_Properties(&pProps)))
  315.     {
  316.         if (SaveProperties)
  317.         {
  318.             if (m_pRectPage != NULL)
  319.             {
  320.                 // Note: the following can fail (for non-rounded rect graphics)
  321.                 //varIndex = "Roundness";//# Localizable string#
  322.                 CString strStr;
  323.                 strStr.LoadString(IDS_STRING3);
  324.                 varIndex = LPCTSTR(strStr);
  325.                 if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  326.                 {
  327.                     varValue = (const long)m_pRectPage->m_roundness;
  328.                     pProp->put_Value(0, &varValue);
  329.                     pProp->Release();
  330.                     varValue.Clear();
  331.                 }
  332.                 bReturn = TRUE;
  333.             }
  334.         }
  335.         else
  336.         {
  337.             ASSERT(m_pRectPage == NULL);
  338.             m_pRectPage = new CRectPage();
  339.  
  340.             // Note: the following can fail (for indeterminate values)
  341.             //varIndex = "Roundness";//# Localizable string#
  342.             CString strStr;
  343.             strStr.LoadString(IDS_STRING3);
  344.             varIndex = LPCTSTR(strStr);
  345.             if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  346.             {
  347.                 if (SUCCEEDED(pProp->get_Value(0, &varValue)) &&
  348.                     varValue.vt == VT_R8)
  349.                     m_pRectPage->m_roundness = varValue.dblVal;
  350.                 pProp->Release();
  351.                 varValue.Clear();
  352.             }
  353.             bReturn = TRUE;
  354.         }
  355.         pProps->Release();
  356.     }
  357.  
  358.     pIGraphic->Release();
  359.     return bReturn;
  360. }
  361.  
  362. void CAutoRect::PageDone(LPDISPATCH ThisRegenMethod, VARIANT FAR* PageNumber) 
  363. {
  364.     // We're finished with the page
  365.     delete m_pRectPage;
  366.     m_pRectPage = NULL;
  367. }
  368.  
  369. BOOL CAutoRect::PropertyPages(LPDISPATCH ThisRegenMethod, VARIANT FAR* PageNumber) 
  370. {
  371.     if (m_pRectPage == NULL)
  372.         return FALSE;
  373.  
  374.     // Run the dialog and get the results
  375.     int nResult = m_pRectPage->DoModal();
  376.     return (nResult == IDOK);
  377. }
  378.  
  379. BOOL CAutoRect::Wizard(LPDISPATCH ThisRegenMethod, VARIANT FAR* WizardNumber) 
  380. {
  381.     // No wizards, so just return FALSE.
  382.     return FALSE;
  383. }
  384.  
  385. void CAutoRect::OnGeometryChanged(LPDISPATCH AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew) 
  386. {
  387. }
  388.  
  389. BOOL CAutoRect::OnGeometryChanging(LPDISPATCH AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew) 
  390. {
  391.     // OK to change our geometry, so just return TRUE.
  392.     return TRUE;
  393. }
  394.  
  395. BOOL CAutoRect::OnNewGraphic(LPDISPATCH AGraphic, BOOL Copy) 
  396. {
  397.     // Return FALSE on failure.
  398.     // For copies, usually do nothing.
  399.     if (Copy)
  400.         return TRUE;
  401.  
  402.     // Add vertices, etc. for new graphic here.
  403.  
  404.     // TODO: Do nothing here.
  405.     IGraphic* pIGraphic = NULL;
  406.     if (FAILED(AGraphic->QueryInterface(IID_IGraphic, (void**)&pIGraphic)))
  407.         return FALSE;
  408.  
  409.     Vertices* pVerts;
  410.     IVertex* pIVertex;
  411.     if (SUCCEEDED(pIGraphic->get_Vertices(&pVerts)))
  412.     {
  413.         COleVariant x;
  414.         COleVariant y;
  415.  
  416.         // First 2 vertices are lower left and upper right corners.
  417.         const double corners[2*2] = { -1.0, -0.5, 1.0, 0.5 };
  418.         for (int i = 0; i < 2*2; )
  419.         {
  420.             x = corners[i++];
  421.             y = corners[i++];
  422.  
  423.             if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  424.                 &f /*penDown*/, 
  425.                 &t /*selectable*/,
  426.                 &f /*snappable*/,
  427.                 &f /*editable*/, 
  428.                 &f /*linkable*/,
  429.                 &f /*calculated*/,
  430.                 &missing /*before*/,
  431.                 &missing /*after*/,
  432.                 &pIVertex)))
  433.                 pIVertex->Release();
  434.         }
  435.  
  436.         // Third vertex is rounding handle (calculated)
  437.         double r = 0.5 * GetRoundness(pIGraphic) / 100.0;
  438.         double offset = 0.1 * r;
  439.         x = 1.0 - r;
  440.         y = 0.5 + offset;
  441.         if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  442.             &f /*penDown*/, 
  443.             &f /*selectable*/,
  444.             &f /*snappable*/,
  445.             &f /*editable*/, 
  446.             &f /*linkable*/,
  447.             &f /*calculated*/,
  448.             &missing /*before*/,
  449.             &missing /*after*/,
  450.             &pIVertex)))
  451.             pIVertex->Release();
  452.  
  453.         // Fourth vertex is rounding handle (editable)
  454.         if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  455.             &f /*penDown*/, 
  456.             &t /*selectable*/,
  457.             &f /*snappable*/,
  458.             &t /*editable*/, 
  459.             &f /*linkable*/,
  460.             &f /*calculated*/,
  461.             &missing /*before*/,
  462.             &missing /*after*/,
  463.             &pIVertex)))
  464.             pIVertex->Release();
  465.  
  466.         pIGraphic->Release();
  467.     }
  468.     return TRUE;
  469. }
  470.  
  471. BOOL CAutoRect::OnCopyGraphic(LPDISPATCH DestGraphic, LPDISPATCH SourceGraphic) 
  472. {
  473.     // Return FALSE on failure.
  474.     return TRUE;
  475. }
  476.  
  477. void CAutoRect::OnPropertyChanged(LPDISPATCH AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew) 
  478. {
  479. }
  480.  
  481. BOOL CAutoRect::OnPropertyChanging(LPDISPATCH AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew) 
  482. {
  483.     // OK to change all of our properties, so just return TRUE.
  484.     return TRUE;
  485. }
  486.  
  487. void CAutoRect::OnPropertyGet(LPDISPATCH AGraphic, long PropID) 
  488. {
  489.     // No special recalculating of properties needed.
  490. }
  491.  
  492. BOOL CAutoRect::Draw(LPDISPATCH AGraphic, LPDISPATCH AView, VARIANT FAR* AMatrix) 
  493. {
  494.     // We don't handle special drawing, so just return FALSE.
  495.     return FALSE;
  496. }
  497.  
  498. BOOL GetVertexXYZ(IGraphic* pIGraphic, const long lVertex, double& x, double& y, double& z)
  499. {
  500.     IVertex* pIVertex = NULL;
  501.     Vertices* pVerts = NULL;
  502.     BOOL bSuccess = FALSE;
  503.     if (SUCCEEDED(pIGraphic->get_Vertices(&pVerts)))
  504.     {
  505.         COleVariant varIndex = lVertex;
  506.         if (SUCCEEDED(pVerts->get_Item(&varIndex, &pIVertex)))
  507.         {
  508.             if (SUCCEEDED(pIVertex->get_X(&x)) &&
  509.                 SUCCEEDED(pIVertex->get_Y(&y)) &&
  510.                 SUCCEEDED(pIVertex->get_Z(&z)))
  511.                 bSuccess = TRUE;
  512.             pIVertex->Release();
  513.         }
  514.         pVerts->Release();
  515.     }
  516.     return bSuccess;
  517. }
  518.  
  519. void AddLineChild(Graphics* pGraphics, double x0, double y0, double x1, double y1)
  520. {
  521.     IGraphic* pChild;
  522.     if (SUCCEEDED(pGraphics->Add(
  523.         &missing /*GraphicType*/,
  524.         &missing /*RegenMethod*/,
  525.         &t /*Inherit*/, 
  526.         &missing /*Style*/,
  527.         &missing /*Before*/,
  528.         &missing /*After*/,                    
  529.         &pChild)))
  530.     {
  531.         pChild->put_Cosmetic(TRUE);
  532.  
  533.         COleVariant x, y;
  534.         Vertices* pVerts = NULL;
  535.         IVertex* pIVertex;
  536.         if (SUCCEEDED(pChild->get_Vertices(&pVerts)))
  537.         {
  538.             x = x0;
  539.             y = y0;
  540.             if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  541.                 &f /*penDown*/, 
  542.                 &t /*selectable*/,
  543.                 &t /*snappable*/,
  544.                 &t /*editable*/, 
  545.                 &t /*linkable*/,
  546.                 &f /*calculated*/,
  547.                 &missing /*before*/,
  548.                 &missing /*after*/,
  549.                 &pIVertex)))
  550.                 pIVertex->Release();
  551.             x = x1;
  552.             y = y1;
  553.             if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  554.                 &t /*penDown*/, 
  555.                 &t /*selectable*/,
  556.                 &t /*snappable*/,
  557.                 &t /*editable*/, 
  558.                 &t /*linkable*/,
  559.                 &f /*calculated*/,
  560.                 &missing /*before*/,
  561.                 &missing /*after*/,
  562.                 &pIVertex)))
  563.                 pIVertex->Release();
  564.             pVerts->Release();
  565.         }
  566.         pChild->Release();
  567.     }
  568. }
  569.  
  570. void AddArcChild(Graphics* pGraphics, double xc, double yc, double r, double start, double end)
  571. {
  572.     IGraphic* pChild;
  573.     COleVariant type((long)imsiArc);
  574.     if (SUCCEEDED(pGraphics->Add(
  575.         &type /*GraphicType*/,
  576.         &missing /*RegenMethod*/,
  577.         &t /*Inherit*/, 
  578.         &missing /*Style*/,
  579.         &missing /*Before*/,
  580.         &missing /*After*/,                    
  581.         &pChild)))
  582.     {
  583.         pChild->put_Cosmetic(TRUE);
  584.         COleVariant x(xc);
  585.         COleVariant y(yc);
  586.         COleVariant rad(r);
  587.         COleVariant sa(start);
  588.         COleVariant ea(end);
  589.  
  590.         pChild->ArcSet(&x, &y, &z, &rad, &missing, &sa, &ea, &missing);
  591.         pChild->Release();
  592.     }
  593. }
  594.  
  595. void CAutoRect::Regen(LPDISPATCH AGraphic) 
  596. {
  597.     IGraphic* pIGraphic = NULL;
  598.     if (FAILED(AGraphic->QueryInterface(IID_IGraphic, (void**)&pIGraphic)))
  599.         return;
  600.  
  601.     long lockCount = 0;
  602.     if (SUCCEEDED(pIGraphic->RegenLock(&lockCount)))
  603.     {
  604.         if (lockCount == 0)
  605.         {
  606.             // TODO:  All the curve processing goes here
  607.             Graphics* pGraphics = NULL;
  608.             IGraphic* pChild = NULL;
  609.             IVertex* pIVertex = NULL;
  610.             if (SUCCEEDED(pIGraphic->get_Graphics(&pGraphics)))
  611.             {
  612.                 COleVariant flags = (const long)GF_COSMETIC;
  613.                 pGraphics->Clear(&flags);
  614.  
  615.                 // Calculate height, width and radius of corners
  616.                     
  617.                 double px[4] = { 0.0 };
  618.                 double py[4] = { 0.0 };
  619.                 double pz[4] = { 0.0 };
  620.                 for (int i = 0; i < 4; ++i)
  621.                     GetVertexXYZ(pIGraphic, i, px[i], py[i], pz[i]);
  622.  
  623.                 BOOL bHandleMoved = !(fabs(px[2] - px[3]) < 0.000001 && 
  624.                     fabs(py[2] - py[3]) < 0.000001);
  625.  
  626.                 double w = fabs(px[1] - px[0]);
  627.                 double h = fabs(py[1] - py[0]);
  628.                 double r = (w < h) ? (w/2.0) : (h/2.0);
  629.                 
  630.                 double roundness;
  631.                 if (bHandleMoved)
  632.                 {
  633.                     if (r == 0.0)
  634.                         roundness = 0.0;
  635.                     else
  636.                     {
  637.                         roundness = fabs(px[2] - px[3]) * 100.0 / r;
  638.                         if (roundness > 100.0)
  639.                             roundness = 100.0;
  640.                     }
  641.                     SetRoundness(pIGraphic, roundness);
  642.                 }
  643.                 else
  644.                 {
  645.                     roundness = GetRoundness(pIGraphic);
  646.                 }
  647.                 r = r * roundness / 100.0;                                        
  648.                     
  649.                 // Add child graphics
  650.                 // Make sure p[0] < p[1]
  651.                 double swap;
  652.                 if (px[0] > px[1])
  653.                 {
  654.                     swap = px[0];
  655.                     px[0] = px[1];
  656.                     px[1] = swap;
  657.                 }
  658.                 if (py[0] > py[1])
  659.                 {
  660.                     swap = py[0];
  661.                     py[0] = py[1];
  662.                     py[1] = swap;
  663.                 }
  664.  
  665.                 if (r == 0.0) 
  666.                 {
  667.                     // No rounded corners
  668.                     // All children are cosmetic
  669.                     if (SUCCEEDED(pGraphics->Add(
  670.                         &missing /*GraphicType*/,
  671.                         &missing /*RegenMethod*/,
  672.                         &t /*Inherit*/, 
  673.                         &missing /*Style*/,
  674.                         &missing /*Before*/,
  675.                         &missing /*After*/,                    
  676.                         &pChild)))
  677.                     {
  678.                         pChild->put_Cosmetic(TRUE);
  679.  
  680.                         COleVariant x, y;
  681.                         Vertices* pVerts = NULL;
  682.                         IVertex* pIVertex;
  683.                         if (SUCCEEDED(pChild->get_Vertices(&pVerts)))
  684.                         {
  685.                             for (int i = 0; i < 4; ++i)
  686.                             {
  687.                                 x = px[(i == 0 || i == 1) ? 0 : 1];
  688.                                 y = py[(i == 0 || i == 3) ? 0 : 1];
  689.                                 if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  690.                                     (i == 0) ? &f : &t /*penDown*/, 
  691.                                     &t /*selectable*/,
  692.                                     &t /*snappable*/,
  693.                                     &t /*editable*/, 
  694.                                     &t /*linkable*/,
  695.                                     &f /*calculated*/,
  696.                                     &missing /*before*/,
  697.                                     &missing /*after*/,
  698.                                     &pIVertex)))
  699.                                     pIVertex->Release();
  700.                             }
  701.                             if (SUCCEEDED(pVerts->AddClose(
  702.                                 &t /*penDown*/, 
  703.                                 &t /*selectable*/,
  704.                                 &t /*snappable*/,
  705.                                 &t /*editable*/, 
  706.                                 &t /*linkable*/,
  707.                                 &f /*calculated*/,
  708.                                 &pIVertex)))
  709.                                 pIVertex->Release();
  710.  
  711.                             pVerts->Release();
  712.                         }
  713.                         pChild->Release();
  714.                     }
  715.                 }
  716.                 else
  717.                     {
  718.                         // Rounded corners
  719.                         // We'll make 4 line children and 4 arc children
  720.                         AddLineChild(pGraphics, px[0] + r, py[0],     px[1] - r, py[0]);
  721.                         AddArcChild (pGraphics, px[1] - r, py[0] + r, r, 1.5 * PI, 0.0);
  722.                         AddLineChild(pGraphics, px[1],     py[0] + r, px[1],     py[1] - r);
  723.                         AddArcChild (pGraphics, px[1] - r, py[1] - r, r, 0.0, 0.5 * PI);
  724.                         AddLineChild(pGraphics, px[1] - r, py[1],     px[0] + r, py[1]);
  725.                         AddArcChild (pGraphics, px[0] + r, py[1] - r, r, 0.5 * PI, PI);
  726.                         AddLineChild(pGraphics, px[0],     py[1] - r, px[0],     py[0] + r);
  727.                         AddArcChild (pGraphics, px[0] + r, py[0] + r, r, PI, 1.5 * PI);
  728.                     }
  729.                 pGraphics->Release();
  730.             }
  731.         }
  732.         pIGraphic->RegenUnlock(&missing);
  733.     }
  734.     pIGraphic->Release();
  735. }
  736.  
  737. BOOL CAutoRect::Initialize(LPDISPATCH ThisRegenMethod) 
  738. {
  739.     // TODO: Add your dispatch handler code here
  740.     return TRUE;
  741. }
  742.  
  743. // DUAL_SUPPORT_START
  744.  
  745. // delegate standard IDispatch methods to MFC IDispatch implementation
  746. DELEGATE_DUAL_INTERFACE(CAutoRect, DualRect)
  747.  
  748. // Our method and property functions can generally just
  749. // delegate back to the methods we generated using 
  750. // ClassWizard. However, if we set up properties to 
  751. // access variables directly, we will need to write the
  752. //  code to get/put the value into the variable.
  753. STDMETHODIMP CAutoRect::XDualRect::get_Description(BSTR FAR* retval)
  754. {
  755.     if (retval == NULL)
  756.         return E_POINTER;
  757.  
  758.     METHOD_PROLOGUE(CAutoRect, DualRect)
  759.  
  760.     TRY_DUAL(IID_ISmartObjectServer)
  761.     {
  762.         *retval = pThis->GetDescription();
  763.         return S_OK;
  764.     }
  765.     CATCH_ALL_DUAL
  766. }
  767.  
  768. STDMETHODIMP CAutoRect::XDualRect::get_ClassID(BSTR FAR* retval)
  769. {
  770.     if (retval == NULL)
  771.         return E_POINTER;
  772.  
  773.     METHOD_PROLOGUE(CAutoRect, DualRect)
  774.  
  775.     TRY_DUAL(IID_ISmartObjectServer)
  776.     {
  777.         *retval = pThis->GetClassID();
  778.         return S_OK;
  779.     }
  780.     CATCH_ALL_DUAL
  781. }
  782.  
  783. STDMETHODIMP CAutoRect::XDualRect::GetPropertyInfo(VARIANT FAR* Names, VARIANT FAR* Types, VARIANT FAR* IDs, VARIANT FAR* Defaults, long FAR* retval)
  784. {
  785.     if (retval == NULL)
  786.         return E_POINTER;
  787.  
  788.     METHOD_PROLOGUE(CAutoRect, DualRect)
  789.  
  790.     TRY_DUAL(IID_ISmartObjectServer)
  791.     {
  792.         *retval = pThis->GetPropertyInfo(Names, Types, IDs, Defaults);
  793.         return S_OK;
  794.     }
  795.     CATCH_ALL_DUAL
  796. }
  797.  
  798. STDMETHODIMP CAutoRect::XDualRect::GetPageInfo(IDispatch * AGraphic, long FAR* StockPages, VARIANT FAR* Names, long FAR* retval)
  799. {
  800.     if (retval == NULL)
  801.         return E_POINTER;
  802.  
  803.     METHOD_PROLOGUE(CAutoRect, DualRect)
  804.  
  805.     TRY_DUAL(IID_ISmartObjectServer)
  806.     {
  807.         *retval = pThis->GetPageInfo(AGraphic, StockPages, Names);
  808.         return S_OK;
  809.     }
  810.     CATCH_ALL_DUAL
  811. }
  812.  
  813. STDMETHODIMP CAutoRect::XDualRect::GetWizardInfo(VARIANT FAR* Names, long FAR* retval)
  814. {
  815.     if (retval == NULL)
  816.         return E_POINTER;
  817.  
  818.     METHOD_PROLOGUE(CAutoRect, DualRect)
  819.  
  820.     TRY_DUAL(IID_ISmartObjectServer)
  821.     {
  822.         *retval = pThis->GetWizardInfo(Names);
  823.         return S_OK;
  824.     }
  825.     CATCH_ALL_DUAL
  826. }
  827.  
  828. STDMETHODIMP CAutoRect::XDualRect::GetEnumNames(long PropID, VARIANT FAR* Names, VARIANT FAR* Values, long FAR* retval)
  829. {
  830.     if (retval == NULL)
  831.         return E_POINTER;
  832.  
  833.     METHOD_PROLOGUE(CAutoRect, DualRect)
  834.  
  835.     TRY_DUAL(IID_ISmartObjectServer)
  836.     {
  837.         *retval = pThis->GetEnumNames(PropID, Names, Values);
  838.         return S_OK;
  839.     }
  840.     CATCH_ALL_DUAL
  841. }
  842.  
  843. STDMETHODIMP CAutoRect::XDualRect::PageControls(IDispatch* ThisRegenMethod, IDispatch * AGraphic, long PageNumber, VARIANT_BOOL SaveProperties, VARIANT_BOOL* retval)
  844. {
  845.     if (retval == NULL)
  846.         return E_POINTER;
  847.  
  848.     METHOD_PROLOGUE(CAutoRect, DualRect)
  849.  
  850.     TRY_DUAL(IID_ISmartObjectServer)
  851.     {
  852.         *retval = pThis->PageControls(ThisRegenMethod, AGraphic, PageNumber, SaveProperties);
  853.         return S_OK;
  854.     }
  855.     CATCH_ALL_DUAL
  856. }
  857.  
  858. STDMETHODIMP CAutoRect::XDualRect::PageDone(IDispatch * ThisRegenMethod, VARIANT FAR* PageNumber)
  859. {
  860.     METHOD_PROLOGUE(CAutoRect, DualRect)
  861.  
  862.     TRY_DUAL(IID_ISmartObjectServer)
  863.     {
  864.         pThis->PageDone(ThisRegenMethod, PageNumber);
  865.         return S_OK;
  866.     }
  867.     CATCH_ALL_DUAL
  868. }
  869.  
  870. STDMETHODIMP CAutoRect::XDualRect::PropertyPages(IDispatch* ThisRegenMethod, VARIANT FAR* PageNumber, VARIANT_BOOL* retval)
  871. {
  872.     if (retval == NULL)
  873.         return E_POINTER;
  874.  
  875.     METHOD_PROLOGUE(CAutoRect, DualRect)
  876.  
  877.     TRY_DUAL(IID_ISmartObjectServer)
  878.     {
  879.         *retval = pThis->PropertyPages(ThisRegenMethod, PageNumber);
  880.         return S_OK;
  881.     }
  882.     CATCH_ALL_DUAL
  883. }
  884.  
  885. STDMETHODIMP CAutoRect::XDualRect::Wizard(IDispatch* ThisRegenMethod, VARIANT FAR* WizardNumber, VARIANT_BOOL* retval)
  886. {
  887.     if (retval == NULL)
  888.         return E_POINTER;
  889.  
  890.     METHOD_PROLOGUE(CAutoRect, DualRect)
  891.  
  892.     TRY_DUAL(IID_ISmartObjectServer)
  893.     {
  894.         *retval = pThis->Wizard(ThisRegenMethod, WizardNumber);
  895.         return S_OK;
  896.     }
  897.     CATCH_ALL_DUAL
  898. }
  899.  
  900. STDMETHODIMP CAutoRect::XDualRect::OnGeometryChanged(IDispatch * AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew)
  901. {
  902.     METHOD_PROLOGUE(CAutoRect, DualRect)
  903.  
  904.     TRY_DUAL(IID_ISmartObjectServer)
  905.     {
  906.         pThis->OnGeometryChanged(AGraphic, GeomID, ParamOld, ParamNew);
  907.         return S_OK;
  908.     }
  909.     CATCH_ALL_DUAL
  910. }
  911.  
  912. STDMETHODIMP CAutoRect::XDualRect::OnGeometryChanging(IDispatch * AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew, VARIANT_BOOL* retval)
  913. {
  914.     if (retval == NULL)
  915.         return E_POINTER;
  916.  
  917.     METHOD_PROLOGUE(CAutoRect, DualRect)
  918.  
  919.     TRY_DUAL(IID_ISmartObjectServer)
  920.     {
  921.         *retval = pThis->OnGeometryChanging(AGraphic, GeomID, ParamOld, ParamNew);
  922.         return S_OK;
  923.     }
  924.     CATCH_ALL_DUAL
  925. }
  926.  
  927. STDMETHODIMP CAutoRect::XDualRect::OnNewGraphic(IDispatch * AGraphic, VARIANT_BOOL Copy, VARIANT_BOOL* retval)
  928. {
  929.     if (retval == NULL)
  930.         return E_POINTER;
  931.  
  932.     METHOD_PROLOGUE(CAutoRect, DualRect)
  933.  
  934.     TRY_DUAL(IID_ISmartObjectServer)
  935.     {
  936.         *retval = pThis->OnNewGraphic(AGraphic, Copy);
  937.         return S_OK;
  938.     }
  939.     CATCH_ALL_DUAL
  940. }
  941.  
  942. STDMETHODIMP CAutoRect::XDualRect::OnCopyGraphic(IDispatch* CopyGraphic, IDispatch* SourceGraphic, VARIANT_BOOL* retval)
  943. {
  944.     if (retval == NULL)
  945.         return E_POINTER;
  946.  
  947.     METHOD_PROLOGUE(CAutoRect, DualRect)
  948.  
  949.     TRY_DUAL(IID_ISmartObjectServer)
  950.     {
  951.         *retval = pThis->OnCopyGraphic(CopyGraphic, SourceGraphic);
  952.         return S_OK;
  953.     }
  954.     CATCH_ALL_DUAL
  955. }
  956.  
  957. STDMETHODIMP CAutoRect::XDualRect::OnPropertyChanged(IDispatch * AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew)
  958. {
  959.     METHOD_PROLOGUE(CAutoRect, DualRect)
  960.  
  961.     TRY_DUAL(IID_ISmartObjectServer)
  962.     {
  963.         pThis->OnPropertyChanged(AGraphic, PropID, ValueOld, ValueNew);
  964.         return S_OK;
  965.     }
  966.     CATCH_ALL_DUAL
  967. }
  968.  
  969. STDMETHODIMP CAutoRect::XDualRect::OnPropertyChanging(IDispatch * AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew, VARIANT_BOOL* retval)
  970. {
  971.     if (retval == NULL)
  972.         return E_POINTER;
  973.  
  974.     METHOD_PROLOGUE(CAutoRect, DualRect)
  975.  
  976.     TRY_DUAL(IID_ISmartObjectServer)
  977.     {
  978.         *retval = pThis->OnPropertyChanging(AGraphic, PropID, ValueOld, ValueNew);
  979.         return S_OK;
  980.     }
  981.     CATCH_ALL_DUAL
  982. }
  983.  
  984. STDMETHODIMP CAutoRect::XDualRect::OnPropertyGet(IDispatch * AGraphic, long PropID)
  985. {
  986.     METHOD_PROLOGUE(CAutoRect, DualRect)
  987.  
  988.     TRY_DUAL(IID_ISmartObjectServer)
  989.     {
  990.         pThis->OnPropertyGet(AGraphic, PropID);
  991.         return S_OK;
  992.     }
  993.     CATCH_ALL_DUAL
  994. }
  995.  
  996. STDMETHODIMP CAutoRect::XDualRect::Draw(IDispatch * AGraphic, IDispatch * AView, VARIANT FAR* AMatrix, VARIANT_BOOL* retval)
  997. {
  998.     if (retval == NULL)
  999.         return E_POINTER;
  1000.  
  1001.     METHOD_PROLOGUE(CAutoRect, DualRect)
  1002.  
  1003.     TRY_DUAL(IID_ISmartObjectServer)
  1004.     {
  1005.         *retval = pThis->Draw(AGraphic, AView, AMatrix);
  1006.         return S_OK;
  1007.     }
  1008.     CATCH_ALL_DUAL
  1009. }
  1010.  
  1011. STDMETHODIMP CAutoRect::XDualRect::Regen(IDispatch* AGraphic)
  1012. {
  1013.     METHOD_PROLOGUE(CAutoRect, DualRect)
  1014.  
  1015.     TRY_DUAL(IID_ISmartObjectServer)
  1016.     {
  1017.         pThis->Regen(AGraphic);
  1018.         return S_OK;
  1019.     }
  1020.     CATCH_ALL_DUAL
  1021. }
  1022.  
  1023. STDMETHODIMP CAutoRect::XDualRect::Initialize(IDispatch* ThisRegenMethod, VARIANT_BOOL* retval)
  1024. {
  1025.     if (retval == NULL)
  1026.         return E_POINTER;
  1027.  
  1028.     METHOD_PROLOGUE(CAutoRect, DualRect)
  1029.  
  1030.     TRY_DUAL(IID_ISmartObjectServer)
  1031.     {
  1032.         *retval = pThis->Initialize(ThisRegenMethod);
  1033.         return S_OK;
  1034.     }
  1035.     CATCH_ALL_DUAL
  1036. }
  1037.  
  1038.  
  1039. // Implement ISupportErrorInfo to indicate we support the 
  1040. // OLE Automation error handler.
  1041. IMPLEMENT_DUAL_ERRORINFO(CAutoRect, IID_ISmartObjectServer)
  1042.  
  1043. // DUAL_SUPPORT_END
  1044.